//本文件用于nextTick。比如，for循环更新响应式100次，只让最后一次触发组件更新 （即，视图更新需要异步，否则将会影响其它代码）
import { fn } from "../reactivity/index.d";
import { runner } from "../reactivity/effect";

/**队列 */
const queue: runner[] = []
/**判断现在是否是job等待状态 */
let isFlushPending = false;
/**Promise.resolve()，用于微任务 */
const p = Promise.resolve();

/**nextTick函数，在这个函数中的callback或await后，就能拿到更新之后的视图 （微任务时执行）
 * @param fn  
 */
export function nextTick(callback?: fn) {
    return callback ? p.then(callback) : p;
}

/**把JOB添加到微任务队列中，同步代码执行完后将会依次执行微任务
 * @param job 
 */
export function queueJob(job: runner) {
    if (!queue.includes(job)) {//没有在队列里才添加 
        queue.push(job)
    }
    queueFlush()
}

/**判断是否需要执行所有的 job*/
function queueFlush() {
    // 如果同时触发了两个组件的更新的话，这里就会触发两次 then （微任务逻辑）
    // 但是这是没有必要的，我们只需要触发一次即可处理完所有的 job 调用
    // 所以需要判断一下 如果已经触发过 nextTick 了， 那么后面就不需要再次触发一次 nextTick 逻辑了
    if (isFlushPending) return
    isFlushPending = true
    nextTick(flushJobs)
}

/**执行所有job */
function flushJobs() {
    isFlushPending = false
    let job: runner | undefined
    while (job = queue.shift()) {
        job && job()
    }
}